package com.carhailing.coupons.parent.child;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.carhailing.common.config.AlipaySign;
import com.carhailing.common.constants.JwtConstants;
import com.carhailing.common.constants.TokenConstants;
import com.carhailing.common.domain.coupons.CouponsVo;
import com.carhailing.common.domain.order.*;
import com.carhailing.common.domain.response.SysUserDto;
import com.carhailing.common.exception.BusinessException;
import com.carhailing.common.interfaces.Codes;
import com.carhailing.common.interfaces.Messages;
import com.carhailing.common.result.Result;
import com.carhailing.common.utils.JwtUtils;
import com.carhailing.coupons.aliPayVo.AlipayVo;
import com.carhailing.coupons.config.AliPayConfig;
import com.carhailing.coupons.mapper.CouponsOrderMapper;
import com.carhailing.coupons.parent.PayHandle;
import com.carhailing.coupons.service.CouponsOrderService;
import com.carhailing.coupons.utils.SnowflakeIdWorker;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Gd
 * @package: parent.child
 * @Project: Online_Taxi_Project
 * @Name: ZhiFuBaoPay
 * @Date: 2024-7-29 10:54
 */
@Service("ZhiFuBao")
@Log4j2
public class ZhiFuBaoPay implements PayHandle {

    @Autowired
    private AliPayConfig aliPayConfig;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private HttpServletRequest servletRequest;

    @Autowired
    private CouponsOrderService couponsOrderService;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private CouponsOrderMapper couponsOrderMapper;

    private String REDISSON_NAME = "alipay_redisson";

    /**
     * 获取支付宝客户端参数
     */
    private DefaultAlipayClient getClient() {
        DefaultAlipayClient alipayClient = new DefaultAlipayClient(
                aliPayConfig.getGatewayUrl(),
                aliPayConfig.getAppId(),
                aliPayConfig.getMerchantPrivateKey(),
                aliPayConfig.getFormat(),
                aliPayConfig.getCharset(),
                aliPayConfig.getAlipayPublicKey(),
                aliPayConfig.getSignType()
        );
        return alipayClient;
    }

    /**
     * 支付宝支付
     */
    @Override
    public String payCarOrder(AlipaySign alipaySign) throws BusinessException {
//    public String payCarOrder(CarPayRecord carPayRecord) {

//        try {
//            //防止用户在多个平台同时请求同一笔订单
//            RLock lock = redissonClient.getLock(REDISSON_NAME + alipaySign.getUserId());
//            boolean tryLock = lock.tryLock(2, 2, TimeUnit.MINUTES);
//
//            if (!tryLock) {
//                throw new BusinessException(Codes.ALIPAY_RESSIONCLIENT, Messages.ALIPAY_RESSIONCLIENT);
//            }
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }

        // 根据订单号查询订单表  是否存在该订单
        CarOrder carOrder = couponsOrderMapper.selectByOrderNumber(alipaySign.getOrderNumber());
        if (null == carOrder) {
            throw new BusinessException(Codes.ORDER_INFO, Messages.ORDER_INFO);
        }
        // 防止重复支付 查询订单流水 支付状态 0  支付中  1  已支付  2  支付失败  3  支付关闭
        List<CarPayRecord> carPayRecords = couponsOrderMapper.selectPayRecordstatusByOrderNumber(alipaySign.getOrderNumber());
        carPayRecords.stream().forEach(carPayRecord -> {
            if (carPayRecord.getPayRecordstatus().equals(0)) {

                AlipayTradeQueryResponse alipayTradeQueryResponse = queryTradeRecord(String.valueOf(alipaySign.getOrderNumber()));
                //支付宝信息不为空
                if (null != alipayTradeQueryResponse) {
                    //并且支付成功
                    if (alipayTradeQueryResponse.isSuccess()) {
                        Integer status = 1;
                        // 修改流水支付状态
                        carOrderRecordupdate(carPayRecord.getPayRecordid(), status);
                        // 修改订单状态
                        carOrderUpdate(carOrder.getStartCarid(), status);
                    }
                }
//                PayHandle bean = (PayHandle) applicationContext.getBean(alipaySign.getType());
//                try {
//                    bean.idStatusZero(carPayRecord);
//                } catch (Exception e) {
//                    throw new RuntimeException(e);
//                }
            }
            if (carPayRecord.getPayRecordstatus().equals(1)) {
                try {
                    throw new BusinessException(Codes.PAY_RECORD_STATUS_ONE, Messages.PAY_RECORD_STATUS_ONE);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });
        // 预留一笔支付流水
        CarPayRecord carPayRecord = insertCarPayRecord(alipaySign.getOrderNumber(), alipaySign.getType(), carOrder);

        log.info("支付宝支付...");
        // 调用三方接口支付
        AlipayClient alipayClient = getClient();
        // 设置请求参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //异步接收地址，仅支持http/https，公网可访问
        request.setNotifyUrl(aliPayConfig.getNotifyUrL());
        //同步跳转地址，仅支持http/https
        request.setReturnUrl(aliPayConfig.getReturnUrl());
        /******必传参数******/
        JSONObject bizContent = new JSONObject();
        //商户订单号，商家自定义，保持唯一性
        bizContent.put("out_trade_no", carOrder.getOrderNumber());
//        bizContent.put("out_trade_no", "1234567890987630");
        //支付金额，最小值0.01元
        bizContent.put("total_amount", carOrder.getPayPrice());
//        bizContent.put("total_amount", "100");
        //订单标题，不可使用特殊符号
        bizContent.put("subject", "测试订单");
        //电脑网站支付场景固定传值FAST_INSTANT_TRADE_PAY
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        // 设置支付宝支付请求的业务参数
        request.setBizContent(bizContent.toString());
        String body = null;
        try {
            // 发起支付宝页面支付请求，使用POST方式提交
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
            // 获取支付宝响应的页面内容
            body = response.getBody();
            System.out.println(body);
            // 判断支付调用是否成功
            System.out.println(response.isSuccess() ? "调用成功" : "调用失败");
        } catch (AlipayApiException e) {
            // 捕获支付宝 API 异常，抛出运行时异常
            throw new RuntimeException(e);
        }
        return body;
    }

    /**
     * 修改订单状态
     */
    private void carOrderUpdate(Long startCarid, Integer status) {
        couponsOrderMapper.carOrderUpdate(startCarid, status);
    }

    /**
     * 修改流水支付状态
     */
    private void carOrderRecordupdate(Long payRecordid, Integer status) {
        couponsOrderMapper.carOrderRecordupdate(payRecordid, status);
    }


    /**
     * 查询第三方的交易流水号
     */
    public AlipayTradeQueryResponse queryTradeRecord(String orderNumber) {
//        AlipayClient alipayClient = new DefaultAlipayClient(
//                aliPayConfig.getAppId(),
//                aliPayConfig.getMerchantPrivateKey(),
//                "json",
//                aliPayConfig.getCharset(),
//                aliPayConfig.getAlipayPublicKey(),
//                aliPayConfig.getSignType());


        DefaultAlipayClient client = getClient();
        AlipayTradeQueryRequest alipayTradePagePayRequest = new AlipayTradeQueryRequest();
        JSONObject object = new JSONObject();
        object.put("out_trade_no", orderNumber);
        alipayTradePagePayRequest.setBizContent(object.toString());
        AlipayTradeQueryResponse execute = null;
        try {
            execute = client.execute(alipayTradePagePayRequest);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

//        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
//
//        request.setBizContent( "{" + "\"out_trade_no\":\"" + orderNumber +"}" );
//        AlipayTradeQueryResponse execute = null;
//        try {
//            execute =  alipayClient.execute(request);
//        } catch (AlipayApiException e) {
//            throw new RuntimeException(e);
//        }

        return execute;
    }

    /**
     * 预留一笔支付流水
     */
    private CarPayRecord insertCarPayRecord(Long orderNumber, String type, CarOrder carOrder) {
        CarPayRecord carPayRecord = new CarPayRecord();
        carPayRecord.setPayRecordordernumber(orderNumber);
        // 使用雪花算法生成唯一、有序的 交易订单号    假设workerId和datacenterId都为0
        SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0, 0);
        long payRecordtradenumber = snowflakeIdWorker.nextId();
        carPayRecord.setPayRecordtradenumber(payRecordtradenumber);
        carPayRecord.setPayRecorduserid(carOrder.getUserId());
        carPayRecord.setPayRecordtype(type);
        carPayRecord.setPayRecordprice(carOrder.getPayPrice());
        carPayRecord.setPayRecordstatus(0);
        carPayRecord.setPayRecordtime(new Date());
        couponsOrderMapper.insertCarPayRecord(carPayRecord);
        return carPayRecord;
    }

    /**
     * 状态：支付中 0
     */
    @Override
    public void idStatusZero(CarPayRecord carPayRecord) throws Exception {
        DefaultAlipayClient client = getClient();
        AlipayTradeQueryRequest alipayTradePagePayRequest = new AlipayTradeQueryRequest();
        JSONObject object = new JSONObject();
        object.put("out_trade_no", carPayRecord.getPayRecordordernumber());
        alipayTradePagePayRequest.setBizContent(object.toString());
        try {
            AlipayTradeQueryResponse response = client.execute(alipayTradePagePayRequest);
            String tradeStatus = response.getTradeStatus();
            if (tradeStatus.equals("TRADE_SUCCESS")) {
               throw new BusinessException(Codes.PAY_RECORD_STATUS_ONE, Messages.PAY_RECORD_STATUS_ONE);
            }
            if (tradeStatus.equals("TRADE_CLOSED") || tradeStatus.equals("WAIT_BUYER_PAY")) {
                // 插入一条支付失败的支付记录
                insertCarPayRecord(carPayRecord);
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 插入一条支付失败的支付记录
     */
    private void insertCarPayRecord(CarPayRecord carPayRecord) {
        CarPayRecord carPayRecord1 = new CarPayRecord();
        carPayRecord1.setPayRecordordernumber(carPayRecord.getPayRecordordernumber());
        carPayRecord1.setPayRecordtradenumber(carPayRecord.getPayRecordtradenumber());
        carPayRecord1.setPayRecorduserid(carPayRecord.getPayRecorduserid());
        carPayRecord1.setPayRecordtype(carPayRecord.getPayRecordtype());
        carPayRecord1.setPayRecordprice(carPayRecord.getPayRecordprice());
        carPayRecord1.setPayRecordstatus(2);
        carPayRecord1.setPayRecordtime(new Date());
        // 插入一条支付失败的支付记录
        couponsOrderMapper.insertCarPayRecord(carPayRecord1);
    }

    /**
     * 主动查询订单接口
     */
    @Override
    public void queryTradeOrder(Long payRecordordernumber, String payRecordtype) throws BusinessException {
        DefaultAlipayClient client = getClient();
        AlipayTradeQueryRequest alipayTradePagePayRequest = new AlipayTradeQueryRequest();
        JSONObject object = new JSONObject();
        object.put("out_trade_no", payRecordordernumber);
        alipayTradePagePayRequest.setBizContent(object.toString());
        AlipayTradeQueryResponse response = null;
        try {
            response = client.execute(alipayTradePagePayRequest);
            String tradeStatus = response.getTradeStatus();
            if(!response.isSuccess()){
                log.info("调用失败原因是：{}" , response.getMsg());
                throw new BusinessException(Codes.QUERY_ORDER_STATUS, Messages.QUERY_ORDER_STATUS);
            }
            CarPayRecord carPayRecord = new CarPayRecord();
            carPayRecord.setPayRecordordernumber(payRecordordernumber);
            if("TRADE_SUCCESS".equals(tradeStatus)){
                carPayRecord.setPayRecordstatus(1);
                couponsOrderService.updateCarOrder(carPayRecord);
            }
            if("TRADE_CLOSED".equals(tradeStatus)){
                carPayRecord.setPayRecordstatus(2);
                couponsOrderService.updateCarOrder(carPayRecord);
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 支付宝支付回调
     *
     * @param request
     * @return
     */
    @Override
    public AlipayVo notifyInfos(HttpServletRequest request) throws BusinessException, AlipayApiException, UnsupportedEncodingException {
        log.info("支付宝异步回调验签...");
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
//       valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                aliPayConfig.getAlipayPublicKey(),
                aliPayConfig.getCharset(),
                aliPayConfig.getSignType()); //调用SDK验证签名

        if (!signVerified) {//验证成功
            throw new BusinessException(Codes.ZHIFUBAO_NOTIFY_ERROR, Messages.ZHIFUBAO_NOTIFY_ERROR);
        }
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        // 付款金额
        String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
        // 回调验签参数
        AlipayVo alipayVo = new AlipayVo(out_trade_no, trade_status,total_amount);
        // 调用SDK验证签名
        return alipayVo;
    }

    /**
     * 退款
     */
    @Override
    public void refundCarOrder(Long orderNumber, CarOrder carOrder) throws BusinessException {
        DefaultAlipayClient alipayClient = getClient();
        AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();

        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(orderNumber.toString());
        model.setRefundAmount(carOrder.getPayPrice().toString());
        refundRequest.setBizContent(JSON.toJSONString(model));

        try {
            //发送请求并处理
            AlipayTradeRefundResponse refundResponse = alipayClient.execute(refundRequest);
            // 退款
            CarOrderRefund carOrderRefund = new CarOrderRefund();
            carOrderRefund.setRefundOrdernumber(orderNumber);
            carOrderRefund.setRefundMoney(carOrder.getPayPrice());
            carOrderRefund.setRefundStatus(1);
            if(refundResponse.getFundChange().equals("Y")){
                carOrderRefund.setRefundStatus(1);
                couponsOrderService.updateCarOrderRefund(carOrderRefund);
                //退款成功收回积分
                SysUserDto userDto = info().getData();
                Integer userIntegral = userDto.getUserIntegral();
                userIntegral = userIntegral- carOrderRefund.getRefundMoney().intValue();
                // 退回积分
                couponsOrderMapper.updateUserIntegralByUserId(userIntegral,userDto.getUserid());
            }else {
                //退款失败
                carOrderRefund.setRefundStatus(2);
                throw new BusinessException(Codes.REFUND_ERROR, Messages.REFUND_ERROR);
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取用户信息
     */
    public Result<SysUserDto> info() {
        String token = servletRequest.getHeader(TokenConstants.TOKEN);
        String userKey = JwtUtils.getUserKey(token);
        String user = redisTemplate.opsForValue().get(JwtConstants.USER_KEY + userKey);
        SysUserDto user1 = JSON.parseObject(user, SysUserDto.class);
        return Result.success(user1);
    }
}
